/**
深拷贝  拷贝后的结果更改是不会影响拷贝之前的 拷贝前后是没有关系的
浅拷贝  改变拷贝前的内容 会对拷贝之后的有影响 拷贝后和拷贝前 是有关系的

引用关系
 */

 let obj = {
     name: 'jw',
     address: {
         x: 100,
         y: 100
     }
 }
 // 无法处理多层关系 多层对象 依旧是浅拷贝
 // ... 运算符 只能拷贝一层
 let o = { ...obj }
 obj.address.x = 200
 console.log(obj, o)
//  console.log(obj == o)

let a = [1, 2, 3]
let arr = [a]
// 也是 浅拷贝
let newArr = arr.slice()
newArr[0][0] = 100
console.log(newArr, arr)

// 深拷贝
let obj = {
    name: 'jw',
    address: {
        x: 100,
        y: 100
    },
    f: function() {},
    un: undefined
}
// 函数会 toString undefined 会丢失
// 深拷贝 (不完整 不能实现复杂的拷贝)
let o = JSON.parse(JSON.stringify(obj))
obj.address.x = 200
console.log(o, obj)

// 实现一个拷贝 实现一个递归拷贝
function deepClone(obj, hash = new WeakMap()) {
    if(obj == null) return obj // 如果是 null 或者 undefined 就不进行拷贝
    if(obj instanceof Date) return new Date(obj)
    if(obj instanceof RegExp) return new RegExp(obj)
    // 可能是对象 或者 是普通值 如果是一个函数的话 是不需要深拷贝的
    if(typeof obj !== 'object') return obj
    // 解决循环引用
    if(hash.get(obj)) return hash.get(obj)
    // 是对象的话就要进行深拷贝 Object.prototype.toString.call(obj) == [object Array]
    // if()
    // console.log(obj.constructor)
    let cloneObj = new obj.constructor
    hash.set(obj, cloneObj)
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            // 实现一个递归拷贝
            cloneObj[key] = deepClone(obj[key], hash) 
        }
    }
    return cloneObj
}
// let obj = null
// let obj = undefined
// let obj = new Date()
// let obj = new RegExp()
// let obj = [1, 2, 3]
let obj = {
    name: 1,
    address: {
        x: 100,
        y: 100
    }
}
obj.o = obj
let d = deepClone(obj)
obj.address.x = 200
console.log(d, obj)
// 如果对象复杂一点 循环引用